package com.jeequan.jeepay.pay.channel.pmopay.payway;

import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.model.params.pmopay.PmopayNormalMchParams;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Base64;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class PaymobPayoutTokenService {


    private String CACHE_TOKEN = "jeepay:payment:paymob-payout:token";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RestTemplate restTemplate;


    /**
     * 获取token
     *
     * @param config
     * @return
     */
    public String getToken(PmopayNormalMchParams config) {
        boolean isNeedRefreshToken = false;
        String accessToken = null;
        String refreshToken = null;

        // 从缓存获取Token
        Object tokenObj = redisTemplate.opsForValue().get(CACHE_TOKEN);
        JSONObject token = null;
        if (tokenObj != null) {
            String tokenJsonString = String.valueOf(tokenObj);
            token = JSONObject.parseObject(tokenJsonString);
            accessToken = token.getString("access_token");
            refreshToken = token.getString("refresh_token");
            long expiresIn = token.getIntValue("expires_in");
            long createTime = token.getLongValue("create_time");
            long duration = System.currentTimeMillis() - createTime;
            // 将预计过期时间提前100秒
            long expiresTime = (expiresIn - 100) * 1000;
            if (duration >= expiresTime) {
                // 需要刷新token
                isNeedRefreshToken = true;
            } else {
                // 如果token没有过期，则直接返回
                return accessToken;
            }
        }

        log.info("参数配置：{}", JSONObject.toJSONString(config));
        StringBuilder sb = new StringBuilder(config.getDomain());
        sb.append("/api/secure/o/token/");

        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();

        if (isNeedRefreshToken) {
            params.add("grant_type", "refresh_token");
            params.add("refresh_token", refreshToken);
        } else {
            // 第一次调获取一个新的Token
            params.add("grant_type", "password");
            params.add("username", config.getUserName());
            params.add("password", config.getPassword());
        }

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
        String basicAuth = String.format("%s:%s", config.getClientId(), config.getSecret());
        headers.add("Authorization", "Basic " + Base64.getEncoder().encodeToString(basicAuth.getBytes()));

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(params, headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(sb.toString(), HttpMethod.POST, httpEntity, String.class);
        log.debug("响应状态：{}，响应结果：{}", responseEntity.getStatusCodeValue(), responseEntity.getBody());
        if (responseEntity.getStatusCode().is2xxSuccessful()) {
            token = JSONObject.parseObject(responseEntity.getBody());
            // 记录Token创建时间
            token.put("create_time", System.currentTimeMillis());
            accessToken = token.getString("access_token");
            long expiresIn = 3600;
            // Token对象写入缓存
            redisTemplate.opsForValue().set(CACHE_TOKEN, JSONObject.toJSONString(token), expiresIn, TimeUnit.SECONDS);
        }
        return accessToken;
    }


}
